<template>
    <div class="table-container">
        <!--表格顶部工具栏-->
        <div class="top-tools" v-if="tools">
            <div class="left">
                <slot name="table-tools"/>
            </div>
            <div class="right" v-show="!loading">
                <i class="refresh el-icon-refresh-right" @click="refresh"></i>
                <span class="line"></span>
                <vab-icon v-if="filterEnable" class="filter " icon="filter-line" @click="onFilterOpen"/>
                <span class="line" v-if="filterEnable"></span>
                <i class="setting el-icon-setting" @click="setting"></i>
            </div>
        </div>
        <el-table :data="(filterStatus && filterRow && data) ? [filterRow,...tableData] : tableData" border
                  :height="height"
                  style="width:100%" ref="table" :row-key="rowKey"
                  :stripe="stripe"
                  v-base-loading="loading"
                  :row-class-name="tableRowClassName"
                  @select="selectChange" @sort-change="sortChange" @select-all="selectAll">
            <!--无数据占位图-->
            <div class="empty-tips" slot="empty"><img :src="require('@/assets/com/image/empty-1.png')"/></div>
            <!--勾选多选-->
            <el-table-column v-if="option.selection===selectionType.checkbox" :reserve-selection="true" type="selection"
                             :selectable="(row,index)=>checkSelectable(row,index)"
                             width="40"/>
            <!--勾选单选-->
            <el-table-column v-if="option.selection===selectionType.radio" width="45" align="center"
                             :fixed="radioFixed">
                <template slot-scope="{row,$index}">
                    <el-radio v-model="radioModel" v-if="!filterStatus || row[rowKey] !== filterRowKey"
                              :label="row[rowKey]"
                              @change="selectChange(row[rowKey])">{{ }}
                    </el-radio>
                </template>
            </el-table-column>
            
            <!--循环列-->
            <el-table-column v-for="(item, index) of option.column"
                             :prop="item.prop"
                             :label="translate(item.label)"
                             :key="item.prop"
                             :sort="item.sort"
                             :sortable="item.sortable ? 'custom' :false"
                             :fixed="item.fixed"
                             min-width="40px"
                             :width="item.width"
                             :show-overflow-tooltip="item.showTip"
                             :align="item.align"
                             :type="item.type">
                
                <template slot-scope="{row,$index}">
                    <!--基础表格行过滤-->
                    <template v-if="filterStatus && row[rowKey] === filterRowKey">
                        <template v-if="item.type === columnType.text || !item.type">
                            <el-input v-model="row[item.prop]"/>
                        </template>
                        <template v-if="item.filterType === 'select'">
                            <el-select v-model="row[item.prop]">
                                <el-option
                                    v-for="item in item.filterOptions"
                                    :key="item.value"
                                    :label="translate(item.label)"
                                    :value="item.value">
                                </el-option>
                            </el-select>
                        </template>
                        <template v-if="item.prop === 'operation' && item.type===columnType.slot">
                            <div class="filter-row-container">
                                <el-tooltip class="item" :content="translate('button.search')" placement="top"
                                            visible-arrow>
                                    <i class="el-icon-search filter-opera" @click="onClickFilter"/>
                                </el-tooltip>
                                <el-tooltip class="item" :content="translate('button.reset')" placement="top"
                                            visible-arrow>
                                    <i class="el-icon-refresh filter-opera" @click="filterReset"/>
                                </el-tooltip>
                            </div>
                        </template>
                    </template>
                    <template v-else>
                        <!--插槽类型-->
                        <template v-if="item.type===columnType.slot">
                            <slot :name="'table-slot-'+item.prop" :row="row" :index="$index"></slot>
                        </template>
                        <!--序号（优先使用传入的，没传出入则使用默认）-->
                        <template v-else-if="item.type===columnType.index">
                            <span>{{ row[item.prop] + 1 || $index + 1 }}</span>
                        </template>
                        <!--图片-->
                        <template v-else-if="item.type===columnType.image">
                            <el-image :src="row[item.prop]"/>
                        </template>
                        <!--图片-->
                        <template v-else-if="item.type===columnType.image">
                            <el-image :src="row[item.prop]"/>
                        </template>
                        <!--普通数据-->
                        <template v-else>{{ !row[item.prop] && row[item.prop] !== 0 ? '—' : row[item.prop] }}</template>
                    </template>
                
                </template>
            </el-table-column>
        </el-table>
        <!--分页-->
        <Pages v-if="data.pageSize"
               :page-size="data.pageSize"
               :page-index="data.pageIndex"
               :total-rows="data.totalRows"
               @pageChange="pageChange"
               @sizeChange="sizeChange"/>
    </div>
</template>
<script lang="ts">
import _ from 'lodash';
import {Component, Emit, Prop, Watch} from "vue-property-decorator";
import BaseVue from '@/common/base-vue'

import BaseTableOptionModel from "@/components-sys/base-table/model/base-table-option.model";
import {ElTable} from "element-ui/types/table";
import Pages from "@/components-sys/pages/page";

import {BaseTableEmitEnum, ColumnTypeEnum, FixedEnum, SelectionEnum} from "./enums/base-table.enum";
import {PageEmitEnum} from "../pages/page-emit.enum";
import ResponseModel from "../../common/model/response.model";
import OrderModel from "../../common/model/order.model";
import {OrderEnum} from "../../common/enum/common.enum";
import PagesModel from "../pages/pages.model";
import LoadingModel from "../loading-directive/loading.model";
import {consoleLog} from "echarts/types/src/util/log";

@Component({components: {Pages}})
export default class BaseTable extends BaseVue {
    
    /*表格数据*/
    @Prop({required: true, type: ResponseModel})
    private data;
    /*表格勾选数据*/
    @Prop()
    private checked: object[] | object;
    /*表格配置*/
    @Prop({required: true, type: BaseTableOptionModel})
    private option: BaseTableOptionModel;
    /*loading状态*/
    @Prop()
    private loading: Boolean | LoadingModel;
    /*表格高度*/
    @Prop(String)
    private height;
    /*表格行row-key*/
    @Prop({required: true, type: String})
    private rowKey;
    /*是否启用筛选*/
    @Prop({default: false})
    private filterEnable: boolean;
    /*斑马纹*/
    @Prop({default: false})
    private stripe: boolean;
    /*是否开启顶部工具栏（默认开启）*/
    @Prop({default: true})
    private tools: boolean;
    /*勾选最大选择数量*/
    @Prop(Number)
    private checkedMax;
    
    /*表格基础组件*/
    private $refs: {
        table: ElTable
    }
    /*列类型*/
    private columnType = ColumnTypeEnum;
    private selectionType = SelectionEnum;
    
    /*勾选数据*/
    private selected: object[] = [];
    
    /*radio绑定的model*/
    private radioModel = '';
    
    /*表格数据（通用表格没有固定的模型）*/
    private tableData = [];
    private filterRow;
    private filterStatus = false;
    private filterRowKey = 'filterRowKey';
    
    /*监听传入的数据*/
    @Watch('data', {deep: true})
    dataChange(val, old) {
        this.tableData = val.data;
    }
    
    /*如果勾选有变动，则更新勾选*/
    @Watch('checked', {deep: true})
    checkedChange(val, old) {
        this.updateChecked();
    }
    
    /*单选是否固定，如果数据有列左固定则必须跟随左固定*/
    get radioFixed() {
        let fixed = null;
        this.option.column.forEach(item => {
            if (item.fixed === FixedEnum.left) {
                fixed = FixedEnum.left;
            }
        })
        return fixed;
    }
    
    /**
     * 生命周期mounted
     */
    private mounted() {
        // 初始化勾选
        this.$nextTick(() => {
            this.updateChecked();
            this.tableData = this.data.data;
        })
    };
    
    /**
     * 更新回显勾选
     */
    public updateChecked() {
        this.$refs.table.clearSelection();
        if (!_.isEmpty(this.checked)) {
            //多选赋值
            if (this.option.selection === SelectionEnum.checkbox) {
                this.selected = [...this.checked]
                this.selected.forEach((item, index) => {
                    // this.$refs.table['selection'].push(item);
                    this.$refs.table.toggleRowSelection(item, true)
                })
            }
            // 单选赋值
            if (this.option.selection === SelectionEnum.radio) {
                this.selected = [_.cloneDeep(this.checked)]
                //单选只能通过tid回显
                this.radioModel = this.selected[0][this.rowKey];
            }
        }
        this.update();
    }
    
    /**
     * 更新表格数据方法
     */
    public update() {
        this.tableData = _.cloneDeep(this.data.data);
        this.$nextTick(() => {
            this.tableData = this.data.data;
        })
    }
    
    /**
     * 勾选事件返回数据，因为传入的数据没有固定的模型，所以勾选也没有返回类型
     */
    @Emit(BaseTableEmitEnum.select)
    private selectChange(val: object[]): object | object[] {
        let res;
        //checkbox返回数组
        if (this.option.selection === SelectionEnum.checkbox) {
            this.selected = res = [...val];
        }
        //radio返回对象
        if (this.option.selection === SelectionEnum.radio) {
            res = this.data.data.find(item => item[this.rowKey] === val);
            this.selected = [res];
        }
        return res;
    }
    
    /**
     * 全选返回数据
     */
    @Emit(BaseTableEmitEnum.select)
    private selectAll(val: object[]): object | object[] {
        return val
    }
    
    /**
     * 排序事件
     */
    @Emit()
    private sortChange({column, prop, order}): OrderModel {
        const orderModel = new OrderModel(prop, OrderEnum[order] as OrderEnum);
        if (_.isEmpty(order)) {
            return null;
        }
        return orderModel;
    }
    
    /**
     * 表格设置按钮事件
     */
    @Emit(BaseTableEmitEnum.setting)
    private setting() {
    }
    
    /**
     * 表格刷新事件
     */
    @Emit(BaseTableEmitEnum.refresh)
    private refresh() {
    }
    
    /**
     * 每页数量切换事件响应
     */
    @Emit(PageEmitEnum.sizeChange)
    private sizeChange(val: PagesModel): PagesModel {
        return val;
    }
    
    /**
     * 当前页改变事件响应
     */
    @Emit(PageEmitEnum.pageChange)
    private pageChange(val: PagesModel): PagesModel {
        return val;
    }
    
    /**
     * 表格行是否禁用勾选（输入行不可勾选、勾选条数超出限制不可勾选）
     */
    private checkSelectable(row: object, index: number): boolean {
        // 如果是输入过滤条件行（固定写死在第一行，因此其他条件均放在else中）
        if (row[this.rowKey] === this.filterRowKey) {
            return false;
        } else {
            // 如果勾选条数大于限制，则设置其他行不可再选（请勿简化此处代码，后期可能会增加条件）
            if (this.checkedMax <= this.selected.length && this.option.selection === SelectionEnum.checkbox &&
                !this.selected.find(item => item[this.rowKey] === row[this.rowKey])) {
                return false;
            } else {
                return true;
            }
        }
    }
    
    /**
     * 打开筛选模式
     */
    private onFilterOpen() {
        if (!_.isEmpty(this.tableData)) {
            if (_.isEmpty(this.filterRow)) {
                this.generateEditRow();
            }
            if (this.filterStatus) {
                this.$emit('close-filter');
            }
            this.filterStatus = !this.filterStatus;
        }
    }
    
    /**
     * 重置筛选条件
     */
    @Emit(BaseTableEmitEnum.filterReset)
    private filterReset() {
        this.generateEditRow();
    }
    
    /**
     * 生成可编辑行
     */
    private generateEditRow() {
        if (!this.filterRow) {
            this.filterRow = _.cloneDeep(this.tableData[0]);
        }
        Object.keys(this.filterRow).forEach(item => {
            this.filterRow[item] = "";
        })
        this.filterRow[this.rowKey] = this.filterRowKey;
    }
    
    /**
     * 点击过滤搜索
     */
    @Emit(BaseTableEmitEnum.onClickFilter)
    private onClickFilter() {
        return Object.assign({}, this.filterRow, {[this.rowKey]: ''});
    }
    
    private tableRowClassName({row}): string {
        if(_.isEmpty(this.checked)){
           return '';
        } else {
            return (this.checked as []).some(item => item[this.rowKey] === row[this.rowKey])
            || (this.checked as Object)[this.rowKey] === row[this.rowKey] ? 'row-selected' : '';
        }
    }
    
};
</script>
<style lang="scss" scoped>
.table-container {
    
    .filter-row-container {
        padding-left: 20px;
        
        .filter-opera {
            font-size: 16px;
            color: $base-color-blue;
            cursor: pointer;
            
            &:not(:last-of-type) {
                margin-right: 20px;
            }
        }
    }
    
    //顶部工具条
    .top-tools {
        display: flex;
        flex-wrap: nowrap;
        padding: 10px 16px;
        background: $base-color-background;
        border: 1px solid $base-border-color;
        border-bottom: none;
        
        .left {
            flex: 1;
            min-height: 23px;;
        }
        
        .right {
            width: 120px;
            text-align: right;
            display: flex;
            align-items: center;
            justify-content: flex-end;
            
            .line {
                width: 1px;
                display: inline-block;
                background: $base-font-color-secondary;
                margin: 0 12px;
                height: 14px
            }
            
            i {
                cursor: pointer;
                font-size: 20px;
            }
        }
    }
    
    ::v-deep.el-radio__label {
        display: none
    }
    
    // 表格图片样式
    .el-table td .cell .el-image {
        width: 60px;
        height: 60px;
        display: block;
        margin: 1.5px auto
    }
    
    ::v-deep.el-table__empty-block {
        width: 100% !important;
    }
    
    .empty-tips {
        img {
            display: block;
            margin: 0 auto
        }
    }
    
}

</style>
